﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Reborn_WorldServer.App1AppHandler;
using Reborn_WorldServer;
using Reborn_Server.App1AppHandler;
using System.IO;
using System.Xml;
using System.Drawing;

namespace App1AppHandler
{
    public class Creature_FrogSummoner : Creature
    {
        public Creature_FrogSummoner(AppHandler2 gameHandler) : base(gameHandler) { }

        public override void runAI()
        {
            base.runAI();

            spawnFrog();
        }

        public override void SetPosition(MapItem mapItem)
        {
            base.SetPosition(mapItem);

            List<CreatureBase> petsToDismiss = new List<CreatureBase>();
            foreach (CreatureBase creatureBase in mapItem.CreaturesBases)
            {
                if (creatureBase.petController != null && creatureBase.petController.MasterCreature == this)
                    petsToDismiss.Add(creatureBase);
            }
            foreach (CreatureBase cb in petsToDismiss)
            {
                //Reset their position now that we're on the tile, it will trigger their effect
                if (cb is Creature_HealSacrifice)
                    cb.SetPosition(mapItem);
            }

        }

        List<SpawnPoint> spawnPoints = new List<SpawnPoint>();

        public override void setXmlData(string xmlData)
        {
            base.setXmlData(xmlData);

            if (xmlData == null || xmlData == "")
                return;

            StringReader sr = new StringReader(xmlData);
            XmlTextReader xmlReader = new XmlTextReader(sr);
            while (xmlReader.Read())
            {
                if (xmlReader.Name == "spawnpoint" && xmlReader.IsStartElement())
                {
                    SpawnPoint sp = new SpawnPoint();
                    sp.mapId = int.Parse(xmlReader.GetAttribute("mapid"));
                    sp.mapX = int.Parse(xmlReader.GetAttribute("mapx"));
                    sp.mapY = int.Parse(xmlReader.GetAttribute("mapy"));

                    spawnPoints.Add(sp);
                }
            }
            xmlReader.Close();
        }

        private Creature_HealSacrifice createSpawn()
        {
            int spawnType = Managers.GameHandler.random.Next(1, 5);

            Creature_HealSacrifice healingSpawn = new Creature_HealSacrifice(Managers.GameHandler);
            CreatureBase s = (CreatureBase)healingSpawn;
            healingSpawn.petController = new Pet_Controller(s, this, currentMapItem);
            this.addPet(healingSpawn.petController);

            //succubus.petController.autoTauntAmount = (SkillManager.AdjustForCombat(CastLevel, 0, CastingCreatureInt) / 2) * -1;

            healingSpawn.MaxHPBase = 100;

            if (spawnType <= 2)
            {
                healingSpawn.Armor = 10000;
                healingSpawn.Agility = 1000;

                if (spawnType == 1)
                    healingSpawn.ImageURL = "FrogNeon10";
                else
                    healingSpawn.ImageURL = "FrogNeon12";
            }
            else
            {
                if (spawnType == 3)
                    healingSpawn.ImageURL = "FrogNeon3";
                else
                    healingSpawn.ImageURL = "FrogNeon8";

                healingSpawn.ResistUnholy = 10000;
                healingSpawn.ResistHoly = 10000;
                healingSpawn.ResistFire = 10000;
                healingSpawn.ResistIce = 10000;
                healingSpawn.ResistMagic = 10000;
                healingSpawn.ResistPhysical = 10000;
            }
            
            

            //succubus.CorpseImageURL = "";
            healingSpawn.CreatureID = Managers.GameHandler.ItemIDGen.GetCreatureUID();
            healingSpawn.CreatureType = "Creature";

            healingSpawn.Defense = 0;
            healingSpawn.DefenseSkill = 0;

            healingSpawn.HandBlockWeapon = "webbed foot";
            //succubus.Dexterity = myCreatureBase.IntelligenceTotal / 2;
            healingSpawn.Faction = Faction;
            healingSpawn.HP = healingSpawn.MaxHPBase;
            healingSpawn.ID = -1;
            healingSpawn.Water = true;
            healingSpawn.Air = false;
            healingSpawn.Land = true;
            
            healingSpawn.Instance = Instance;
            //succubus.Intelligence = myCreatureBase.Intelligence / 2;

            healingSpawn.MaxManaBase = 5;
            healingSpawn.Mana = 5;

            healingSpawn.MapID = MapID;

            healingSpawn.MaxMoves = 1;
            healingSpawn.MovementSpeed = 3;

            healingSpawn.MaxStaminaBase = 5;
            healingSpawn.Name = "Gluk Spawn";
            healingSpawn.SoundDeath = "SpiderDeath";
            healingSpawn.Stamina = healingSpawn.MaxStaminaBase;
            //succubus.Strength = myCreatureBase.IntelligenceTotal / 2;
            //succubus.Wisdom = myCreatureBase.WisdomTotal / 2;

            healingSpawn.Timer_Regen.Start();
            healingSpawn.creatureAI.Timer_CreatureRound.Start();

            CreatureAttackWeapon basicWeapon = new CreatureAttackWeapon();
            basicWeapon.Accuracy = 1;
            basicWeapon.Description = "strikes {name}";
            basicWeapon.DmgHigh = 10;
            basicWeapon.DmgLow = 1;
            basicWeapon.Frequency = 1;
            basicWeapon.Sequence = 1;
            basicWeapon.SkillLevel = 1;
            basicWeapon.Speed = 3.1M;

            healingSpawn.attackSequenceManager.Attacks.Add(basicWeapon);
            healingSpawn.buffManager.HasInnateNightVision = true;

            return healingSpawn;
        }

        private MapItem findRandomSpawnPoint()
        {
            List<Point> hiddenList = CreatureAI.FindHidden(this, currentMapItem.mapItemsWithin4, true);

            List<MapItem> availableMapItems = new List<MapItem>();
            foreach (MapItem mapItem in currentMapItem.mapItemsWithin4)
            {
                if (mapItem.Motion > 0 && CreatureAI.isHidden(mapItem.MapX, mapItem.MapY, hiddenList) == false)
                {
                    foreach (SpawnPoint sp in spawnPoints)
                    {
                        if (mapItem.parentMap.MapID == sp.mapId && mapItem.MapX == sp.mapX && mapItem.MapY == sp.mapY && mapItem != currentMapItem)
                        {
                            availableMapItems.Add(mapItem);
                            break;
                        }
                    }
                }
            }

            if (availableMapItems.Count == 0)
                return null;

            return availableMapItems[Managers.GameHandler.random.Next(availableMapItems.Count)];
        }

        private bool doSpawn = false;
        private void spawnFrog()
        {
            doSpawn = !doSpawn;
            if (doSpawn == false)
                return;

            LockItem lockItem = Managers.GameHandler.GetLockItem(MapID, Instance);
            lock (lockItem.LockObj)
            {
                //CHECK IF WE'RE IN A VALID STATE TO CONTINUE EXECUTION/////////////////////////

                //System.Reflection.MethodBase currentMethodBase = System.Reflection.MethodBase.GetCurrentMethod();
                //Delegate currentMethodDelegate = Delegate.CreateDelegate(currentMethodBase.GetType(), this, currentMethodBase.Name);

                //Create a delegate for this method incase it cant be run right now
                Action thisMethod = (Action)spawnFrog;
                //Record this method's arguments
                Object[] thisMethodArgs = { null };
                //Pass the delegate and args when we check if we're mid map transfer. If yes, they will be recorded and run again automatically.
                if (isChangingMaps(thisMethod, thisMethodArgs) == true)
                    return;

                //A map transfer happened, but its already complete. Immediately re-run this method on a different thread. 
                //We need to use a different thread because otherwise the current thread would lock 2 maps possibly resulting in a deadlock.
                if (MapID != lockItem.MapID)
                {
                    thisMethod.BeginInvoke(null, null);
                    return;
                }
                //STATE IS VALID, CONTINUE EXECUTION///////////////////////////////////////////

                if (HP > MaxHP * .75 || HP < 1)
                    return;

                MapItem mapitemToUpdate = findRandomSpawnPoint();

                if (mapitemToUpdate != null)
                {
                    Creature_HealSacrifice healingSpawn = createSpawn();

                    List<Character> CharsToUpdate = new List<Character>();
                    foreach (MapItem mapitem in mapitemToUpdate.mapItemsWithin8)
                    {
                        foreach (CreatureBase creaturebase in mapitem.CreaturesBases)
                        {
                            if (creaturebase is Character)
                                CharsToUpdate.Add((Character)creaturebase);
                        }
                        if (mapitem.MapX == mapitemToUpdate.MapX && mapitem.MapY == mapitemToUpdate.MapY)
                        {
                            healingSpawn.SetPosition(mapitem);
                            mapitem.CreaturesBases.Add(healingSpawn);
                        }
                    }
                    foreach (Character character in CharsToUpdate)
                    {
                        //character.PlaySound(soundToPlay.Name, soundToPlay.MapX, soundToPlay.MapY);
                        character.AddMapItem(mapitemToUpdate);
                        //if (character == myCreatureBase)
                        //    character.petManager.AddPet(succubus.petController);
                    }
                }

            }
        }
    }
    class SpawnPoint
    {
        public SpawnPoint() { }

        public int mapId;
        public int mapX;
        public int mapY;
    }
}
